package cn.gok.util;

import cn.gok.entity.Student;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.sql.Connection;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @Author: chen fan
 * @Date: 2022/3/10 11:20
 * @Description:  自定义工具类，将 request 中map里的数据取出，封装到一个对象中并返回
 */
public class MapObjectMapper {

    /**
     * 将request中的数据取出，转成任意我们需要的对象
     * @param request  请求对象
     * @param clazz    要转换对象的 类型
     */
    public static <T> T getObject(HttpServletRequest request,Class<T> clazz){
        //1、先获取request中的参数
        Map<String, String[]> parameterMap = request.getParameterMap();

        T instance = null;
        try {
            //2、再根据Class 创建出我们需要的对象
            instance  = clazz.getConstructor().newInstance();

            /*
                3、将map中数据一一取出存入instance中
                    map中的key 就是对象的属性名，
                    如果key  在 对象中找不到对应的属性，就不管这个属性，赋值
             */
            Set<String> keys = parameterMap.keySet();

            Field[] declaredFields = clazz.getDeclaredFields();
            for (String key : keys) {
                //如果key对应的属性存在，我们才对此属性进行赋值
                if (fieldIsExit(declaredFields,key)) {

                    //获取key对应的属性
                    Field field = clazz.getDeclaredField(key);

                    //打破属性的私有封装
                    field.setAccessible(true);
                    String[] values = parameterMap.get(key);
                    setFieldValue(instance,field,values);
                }
            }
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return instance;
    }


    /**
     * 用来实现对属性赋值
     *       一般前端表单提交的数据都是字符串，
     *                             我们在做属性封装时，实体类中属性的类型一般都是
     *                             String、整数、浮点数、布尔值、日期
     *
     *      中间实现时，需要判断该属性的数据类是String、整数、浮点数、布尔值、日期中的哪一个，
     *      然后需要将字符串value转成对应的类型以后，才能赋值
     * @param field
     * @param values
     * @param obj
     */
    private static void setFieldValue(Object obj,Field field,String[] values) throws IllegalAccessException, ParseException {
        Class<?> fieldType = field.getType();

         /*
            values的长度是>1 则说明，提交过来key对应数据有多个值，比如像复选框的数据，

            多个数据时，属性类型要么是数组，要么是集合
         */
        if (values.length >1){

            if (fieldType.isArray()){
                field.set(obj, values);
            }else {
                //将数组转成集合
                List<String> strings = Arrays.asList(values);
                field.set(obj, strings);
            }
            return;
        }

        /*
          如果不大于1，则说明就是单个值，单个赋值即可
         */
        String value = values[0];
        if (value == null || value == ""){
            field.set(obj, null);
        } else if (fieldType.equals(String.class)){
            field.set(obj,value);
        }else if (fieldType.equals(Date.class)){
            Date date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(value);
            field.set(obj,date);
        }else if (fieldType.equals(Boolean.class) || fieldType.equals(boolean.class)){
            Boolean aBoolean = Boolean.valueOf(value);
            field.set(obj,aBoolean);
        }else if(fieldType.equals(Integer.class) || fieldType.equals(int.class)){
            field.set(obj, Integer.parseInt(value));
        }else if(fieldType.equals(Long.class) || fieldType.equals(long.class)){
            field.set(obj, Long.parseLong(value));
        }else if(fieldType.equals(Short.class) || fieldType.equals(short.class)){
            field.set(obj, Short.parseShort(value));
        }else if(fieldType.equals(Byte.class) || fieldType.equals(byte.class)){
            field.set(obj, Byte.parseByte(value));
        }else if(fieldType.equals(Double.class) || fieldType.equals(double.class)){
            field.set(obj, Double.parseDouble(value));
        }else if(fieldType.equals(Float.class) || fieldType.equals(float.class)){
            field.set(obj, Float.parseFloat(value));
        }
    }


    /**
     * 判断map中的key  在相应对象 是否有对应属性存在
     * @return  返回true表示存在，返回false表示不存在
     */
    private static boolean fieldIsExit(Field[] fields,String key){
        for (Field field : fields) {
            if (field.getName().equals(key)){
                return true;
            }
        }
        return false;
    }
}
